/*
 *    Copyright (c) 2006 ThoughtWorks, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.thoughtworks.turtlemock.internal;

import com.thoughtworks.turtlemock.constraint.Constraint;
import junit.framework.Assert;

public class OnceAssertedInvokeMethodResultLog extends AbstractRollbackableInvokeLog implements InvokeMethodResultLog {

    private final InvokeMethodResultLog invokeMethodResultLog;

    public OnceAssertedInvokeMethodResultLog(InvokeMethodResultLog invokeMethodResultLog) {
        this.invokeMethodResultLog = invokeMethodResultLog;
        this.invokeMethodResultLog.times(1);
    }

    public InvokeWithArgsResultLog with(Object param) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.with(param));
    }

    public InvokeWithArgsResultLog with(Object param1, Object param2) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.with(param1, param2));
    }

    public InvokeWithArgsResultLog with(Object param1, Object param2, Object param3) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.with(param1, param2, param3));
    }

    public InvokeWithArgsResultLog with(Object param1, Object param2, Object param3, Object param4) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.with(param1, param2, param3, param4));
    }

    public InvokeWithArgsResultLog withArgs(Object[] args) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.withArgs(args));
    }

    public InvokeWithArgsResultLog withAllArgsConstraint(Constraint c) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.withAllArgsConstraint(c));
    }

    public InvokeWithArgsResultLog withFirstArgConstraint(Constraint constraint) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.withFirstArgConstraint(constraint));
    }

    public InvokeWithArgsResultLog withArgsConstraint(Constraint[] constrains) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.withArgsConstraint(constrains));
    }

    public InvokeWithArgsResultLog withArgConstraint(Constraint constraint, int paramIndex) {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.withArgConstraint(constraint, paramIndex));
    }

    public InvokeWithArgsResultLog noArgs() {
        rollback();
        return assertTimesExpection(invokeMethodResultLog.noArgs());
    }

    public InvokeMethodResultLog then(String operationName) {
        return this.invokeMethodResultLog.then(operationName);
    }

    public void times(int times) {
        rollback();
        invokeMethodResultLog.times(times);
    }

    public int timesNotAsserted() {
        return invokeMethodResultLog.timesNotAsserted();
    }

    public void rollback() {
        invokeMethodResultLog.rollback();
    }

    public String getOperationName() {
        return invokeMethodResultLog.getOperationName();
    }

    public InvokeMethodResultLog inAnotherThread() {
        return invokeMethodResultLog.inAnotherThread();
    }

    private InvokeWithArgsResultLog assertTimesExpection(InvokeWithArgsResultLog timesExpection) {
        Assert.assertTrue(timesExpection.status().getMsg(), timesExpection.status().isFullFilled());
        return new OnceAssertedInvokeWithArgsResultLog(timesExpection);
    }
}
